package cn.flying.cloud.base.mail.service;

import javax.annotation.Resource;
import javax.mail.internet.MimeMessage;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.util.CollectionUtils;

import com.sun.mail.util.MailSSLSocketFactory;

import cn.flying.cloud.base.mail.exception.MsgException;

/**
 * 发送邮件服务类
 *
 * @author: admin
 * @date: 2024年05月28日 12:59
 * @version: 1.0
 */
public class MailSenderService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * Spring Boot 提供了一个发送邮件的简单抽象，使用的是下面这个接口，这里直接注入即可使用
     */
    @Resource
    private JavaMailSender mailSender;
    /**
     * Spring Boot 提供的默认的属性配置类
     */
    @Resource
    private MailProperties mailProperties;

    /**
     * 简单文本邮件
     *
     * @param to      收件人
     * @param subject 主题（标题）
     * @param content 内容
     */
    public void sendSimpleMail(List<String> to, String subject, String content) throws MsgException {
        logger.info("发送简单文本邮件，接收人[{}]，主题[{}]，邮件内容[{}]", to, subject, content);
        //创建SimpleMailMessage对象
        SimpleMailMessage message = new SimpleMailMessage();
        //邮件发送人（这里要和认证用户邮箱匹配）
        message.setFrom(mailProperties.getUsername());
        //邮件接收人
        message.setTo(to.toArray(new String[0]));
        //邮件主题
        message.setSubject(subject);
        //邮件内容
        message.setText(content);
        //发送邮件
        try {
            setSsl(mailSender);
            mailSender.send(message);
            logger.info("邮件已经发送成功！");
        } catch (Exception e) {
            logger.error("邮件发送失败，原因：[{}]", e.getMessage());
            throw new MsgException("邮件发送失败！", e);
        }
    }

    /**
     * 简单文本邮件
     *
     * @param to        收件人
     * @param subject   主题（标题）
     * @param content   内容
     * @param filePaths 附件（注意这里的filePath必须是服务器本地文件路径，不能是远程文件链接）
     */
    public void sendSimpleMail(List<String> to, String subject, String content, List<String> filePaths) throws MsgException {
        try {
            //获取MimeMessage对象
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            //邮件发送人（这里要和认证用户邮箱匹配）
            helper.setFrom(mailProperties.getUsername());
            //邮件接收人
            helper.setTo(to.toArray(new String[0]));
            //邮件主题
            message.setSubject(subject);
            //邮件内容，html格式
            helper.setText(content, false);
            //可以同时添加多个附件
            if (filePaths != null) {
                for (String path : filePaths) {
                    FileSystemResource resource = new FileSystemResource(new File(path));
                    helper.addAttachment(Objects.requireNonNull(resource.getFilename()), resource);
                }
            }

            setSsl(mailSender);
            //发送
            mailSender.send(message);

            logger.info("邮件已经发送成功！");
        } catch (Exception e) {
            logger.error("邮件发送失败，原因：[{}]", e.getMessage());
            throw new MsgException("邮件发送失败！", e);
        }
    }

    /**
     * 设置SSL
     *
     * @param mailSender
     */
    private void setSsl(JavaMailSender mailSender) throws Exception {
        JavaMailSenderImpl impl = (JavaMailSenderImpl) mailSender;
        Properties props = impl.getJavaMailProperties();
        if ("true".equals(props.get("mail.smtp.ssl.enable"))) {
            MailSSLSocketFactory sf = new MailSSLSocketFactory("TLSv1.2");
            sf.setTrustAllHosts(true);
            props.put("mail.smtp.ssl.enable", "true");
            props.put("mail.smtp.ssl.socketFactory", sf);
            impl.setJavaMailProperties(props);
        }
    }

    /**
     * html邮件
     *
     * @param to        收件人
     * @param subject   主题（标题）
     * @param content   内容
     * @param filePaths 附件（注意这里的filePath必须是服务器本地文件路径，不能是远程文件链接）
     */
    public void sendHtmlMail(List<String> to, String subject, String content, List<String> filePaths) throws MsgException {
        logger.info("发送Html邮件，接收人[{}]，主题[{}]，邮件内容[{}]", to, subject, content);
        try {
            //获取MimeMessage对象
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            //邮件发送人（这里要和认证用户邮箱匹配）
            helper.setFrom(mailProperties.getUsername());
            //邮件接收人
            helper.setTo(to.toArray(new String[0]));
            //邮件主题
            message.setSubject(subject);
            //邮件内容，html格式
            helper.setText(content, true);
            //可以同时添加多个附件
            if (!CollectionUtils.isEmpty(filePaths)) {
                for (String filePath : filePaths) {
                    FileSystemResource resource = new FileSystemResource(new File(filePath));
                    helper.addAttachment(Objects.requireNonNull(resource.getFilename()), resource);
                }
            }

            setSsl(mailSender);
            //发送
            mailSender.send(message);

            logger.info("邮件已经发送成功！");
        } catch (Exception e) {
            logger.error("邮件发送失败，原因：[{}]", e.getMessage());
            throw new MsgException("邮件发送失败！", e);
        }
    }

    /**
     * 发送嵌入图片的邮件
     *
     * @param to      收件人
     * @param subject 主体
     * @param content 内容
     * @param imgMap  图片名，路径的映射，用于在<img\>标签中使用，从而显示图片
     */
    public void sendInlineImgMail(List<String> to, String subject, String content, Map<String, String> imgMap) throws MsgException {
        logger.info("发送静态嵌入图片的邮件，接收人[{}]，主题[{}]，邮件内容[{}]", to, subject, content);
        try {
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true);
            //邮件发送人（这里要和认证用户邮箱匹配）
            helper.setFrom(mailProperties.getUsername());
            //邮件接收人
            helper.setTo(to.toArray(new String[to.size()]));
            //邮件主题
            helper.setSubject(subject);
            //邮件内容
            helper.setText(content, true);
            // 添加多个图片
            for (Map.Entry<String, String> entry : imgMap.entrySet()) {
                FileSystemResource resource = new FileSystemResource(new File(entry.getValue()));
                if (resource.exists()) {
                    helper.addInline(entry.getKey(), resource);
                }
            }

            setSsl(mailSender);
            mailSender.send(message);
            logger.info("邮件已经发送成功！");
        } catch (Exception e) {
            logger.error("邮件发送失败，原因：[{}]", e.getMessage());
            throw new MsgException("邮件发送失败！", e);
        }
    }
}